#include "Line.hpp"
#include <iostream>

using std::cout;
using std::endl;
using std::ostream;


class Line::LineImpl
{
private:
    //将Point设置为Line的私有类型，意味Point只会Line服务，
    //不希望Point在Line类之外被使用
    class Point {
    public:
        //explicit关键字的作用是禁止隐式转换
        explicit
        Point(int ix = 0, int iy = 0)
        : _ix(ix)
        , _iy(iy)
        {
            cout << "Point(int,int)" << endl;
        }

        ~Point() {  cout << "~Point()" << endl;}

        void print() const
        {
            cout << "(" << _ix 
                 << "," << _iy
                 << ")";
        }

        friend ostream & operator<<(ostream &os, const Point & rhs);
        
    private:
        int _ix;
        int _iy;
        int _iz;
    };
    
public:
    LineImpl(int x1, int y1, int x2, int y2)
    : _pt1(x1, y1)
    , _pt2(x2, y2)
    {
        cout << "LineImpl(int,int,int,int)" << endl;
    }

    ~LineImpl() {   cout << "~LineImpl()" << endl;  }

    void printLine() const 
    {
        _pt1.print();
        cout << " --> ";
        _pt2.print();
        cout << endl;
    }

    //friend ostream & operator<<(ostream &os, const LineImpl::Point & rhs);
private:
    Point _pt1;
    Point _pt2;
};

//输出流运算符函数既要访问Point中的私有成员，
//也要访问Line中的私有的Point嵌套类
//因此需要将该函数同时设置为Line和Point的友元
#if 0
ostream & operator<<(ostream &os, const Line::LineImpl::Point & rhs)
{
    os << "(" << rhs._ix
       << "," << rhs._iy
       << ")";
    return os;
}
#endif


Line::Line(int x1, int y1, int x2, int y2)
: _pimpl(new LineImpl(x1, y1, x2, y2))
{   cout << "Line(int,int,int,int)" << endl;}

Line::~Line()
{   
    cout << "~Line()" << endl;
    if(_pimpl) {
        delete _pimpl;
        _pimpl = nullptr;
    }
}

void Line::printLine() const
{
    _pimpl->printLine();
}
